package com.wlz.creational.singleton;

import com.wlz.creational.singleton.enumSingleton.Singleton;
import com.wlz.creational.singleton.hunger.HungrySingleton;
import com.wlz.creational.singleton.lazy.LazySingleton;
import org.junit.Test;

import java.io.*;

/**
 * @author： wlz
 * @Date 2020/7/21 10:16
 * @description： TODO
 * @version: 1.0
 *  利用序列化与反序列化破坏单例模式
 */
public class SerializationMain {

    /**
     * 饿汉式    通过序列化,反序列化
     * 解决思路:实现readResolve
     */
    @Test
    public void test1() throws Exception {
        HungrySingleton singleton = HungrySingleton.getInstance();

        // 创建输出流
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("singletonFile"));

        // 将单例对象写到文件中
        out.writeObject(singleton);

        // 从文件中读取单例对象
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("singletonFile"));

        HungrySingleton newSingleton = (HungrySingleton) in.readObject();

        // 判断是否是同一个对象
        System.out.println(newSingleton == HungrySingleton.getInstance()); // false
    }

    /**
     * 懒汉式
     *
     * @throws Exception
     */
    @Test
    public void test2() throws Exception {
        // 创建输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("LazySingleton.file"));
        // 将单例对象写到文件中
        oos.writeObject(LazySingleton.getInstance());
        // 从文件中读取单例对象
        File file = new File("LazySingleton.file");
        ObjectInputStream ois =  new ObjectInputStream(new FileInputStream(file));
        LazySingleton newInstance = (LazySingleton) ois.readObject();
        // 判断是否是同一个对象
        System.out.println(newInstance == LazySingleton.getInstance()); // false

    }


    /**
     * 枚举方式序列化 反序列化攻击
     */
    @Test
    public void test3() throws Exception {
        Singleton singleton = Singleton.INSTANCE;

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("singletonFile"));
        out.writeObject(singleton);

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("singletonFile"));

        Singleton newSingleton = (Singleton) in.readObject();

        System.out.println(singleton.hashCode());
        System.out.println(newSingleton.hashCode());

    }

}
